/***************************************************************************\
 * Copyright (C) by Keio University
 * VAO.hpp created in 01 2012.
 * Mail : fdesorbi@hvrl.ics.keio.ac.jp
 *
 * VAO.hpp is part of the HVRL Engine Library.
 *
 * The HVRL Engine Library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 3 of the License, or
 * (at your option) any later version.
 *
 * The HVRL Engine Library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
\***************************************************************************/

#ifndef HVRL_VAO_HPP__
#define HVRL_VAO_HPP__

#include "hvrl/common/Common.hpp"

#include <GL/glew.h>

#if CUDA_AVAILABLE == 1
#include "hvrl/gpgpu/cuda/Prototypes.hpp"
#endif

namespace hvrl
{
/**
* /brief This class manages a custom Vertex Array Object
*
* It can contain any kind of geometry
*
*/
class VAO
{

public:

    GLuint vertexarrayid;
    GLuint verticesid;
    GLuint normalsid;
    GLuint texturesid;
    GLuint colorsid;
    GLuint indicesid;

    GLint verticesattribid;
    GLint normalsattribid;
    GLint texturesattribid;
    GLint colorsattribid;

#if CUDA_AVAILABLE == 1
    struct cudaGraphicsResource *ressource_v;
    struct cudaGraphicsResource *ressource_c;
    struct cudaGraphicsResource *ressource_n;
#endif

private:

    unsigned int indices;
    bool initialized;
    GLenum memorystorage;
    bool hasshader;

public:

    VAO(void);

    bool init(const float* vertexbuffer,
        const unsigned int& sizevertices,
        const unsigned int* indicebuffer,
        const unsigned int& sizeindices,
        const float* normalbuffer = 0,
        const float* texturebuffer = 0,
        const float* colorbuffer = 0,
        const GLenum& memorystorage = GL_DYNAMIC_DRAW);

    ~VAO(void);

    bool setProgramObject(const GLuint& po);

    bool hasProgramObject(void) {
    	return this->hasshader;
    }

    bool updateVertices(const float* vertexbuffer,
                      const unsigned int& sizevertices, const GLenum& memorystorage = GL_DYNAMIC_DRAW);
    bool updateIndices(const GLuint* indicebuffer,
                        const unsigned int& sizeindices, const GLenum& memorystorage = GL_DYNAMIC_DRAW);
    bool updateNormals(const float* normalbuffer,
                       const unsigned int& sizenormals, const GLenum& memorystorage = GL_DYNAMIC_DRAW);
    bool updateTextures(const float* texturebuffer,
                        const unsigned int& sizetextures, const GLenum& memorystorage = GL_DYNAMIC_DRAW);
    bool updateColors(const float* colorbuffer,
                        const unsigned int& sizecolor, const GLenum& memorystorage = GL_DYNAMIC_DRAW);

    void draw(const GLenum& aspecttype) const;

    void getVerticesArray(GLvoid ** pointer);
    void getNormalsArray(GLvoid ** pointer);
    void getTexturesArray(GLvoid ** pointer);
    void getColorsArray(GLvoid ** pointer);

protected:

    void destroy(void);





};

}


#endif
